package weeny.pre.face;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import java.util.regex.Pattern;

import javax.swing.DefaultCellEditor;
import javax.swing.JColorChooser;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.event.CellEditorListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.tree.TreeCellEditor;

import prefuse.data.parser.DataParseException;
import prefuse.util.ColorLib;
import weeny.pre.io.parser.ColorParser;
import weeny.pre.util.IntColor;
import weeny.util.logs.Debug;

/**
 * This is a jtextfield, which you can right click to invoke a color chooser.
 * 
 * It also implements several interface so you can directly use.
 *  
 * @author weeny
 */
public class ColorTextField extends JTextField implements TableCellRenderer, 
                                                TableCellEditor, TreeCellEditor{

	/**
	 * Any field name matches this pattern will be considered as integer colors.
	 * It matches something like "_????Color" or "_???Color:???".
	 */
	public static Pattern COLOR_FLD_PATTERN = 
		Pattern.compile("_[a-z]+Color(?::[a-z]+)?");
	
	
	private ColorParser colorParser = new ColorParser();
	private JTextField panel = new JTextField();{
		panel.setBorder(null);
	}
	private DefaultCellEditor editor = null;
	
	private String formatColor(Object integer){
		return colorParser.format(integer);
	}
	private int parseColor(Object value){
		try {
			return (Integer) colorParser.parse(value.toString());
		} catch (DataParseException e) {
			Debug.prob("cannot get color from "+value+", use RED insead!");
			return ColorLib.color(Color.RED);
		}
	}
	
	public void setColor(Object intColor){
		super.setText(formatColor(intColor));
	}
	
	public int getColor(){
		return parseColor(super.getText());
	}
	
	public ColorTextField() {
		this.setOpaque(true);
		this.addFocusListener(new FocusListener() {
			public void focusLost(FocusEvent e) {
				int color = ColorTextField.this.getColor();
				setBackground(ColorLib.getColor(color));
				setForeground(ColorLib.getColor(color));
			}
			public void focusGained(FocusEvent e) {
				setBackground(Color.WHITE);
				setForeground(Color.BLACK);
			}
		});
		addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.getButton() != MouseEvent.BUTTON3) {
					return;
				}
				int color = ColorTextField.this.getColor();
				Debug.info("Open colorChooser for : "+formatColor(color));
				Color valCol = ColorLib.getColor(color);
				Color newCol = JColorChooser.showDialog(null, "", valCol);
				if (newCol != null) {
					int a = ColorLib.alpha(color);
					color = ColorLib.setAlpha(ColorLib.color(newCol), a);
					ColorTextField.this.setColor(color);
					postActionEvent();//fireActionEvent!
					Debug.info("Color setting is done");
				}
				else{
					Debug.info("Color setting is canceled");
				}
			}
		});
		editor = new DefaultCellEditor(this);
	}
	
	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int column) {
		if (value == null) {
			return panel;
		}
		int color = parseColor(value);
		if (isSelected)
			color = ColorLib.interp(IntColor.BLUE, color, 0.8);
		panel.setBackground(ColorLib.getColor(color));
		return panel;
	}
	
	
	public DefaultCellEditor toCellEditor(){
		DefaultCellEditor editor = new DefaultCellEditor(this);
		return editor;
	}
	public Object getCellEditorValue() {
		return editor.getCellEditorValue();
	}
	public boolean isCellEditable(EventObject anEvent) {
		return editor.isCellEditable(anEvent);
	}
	public boolean shouldSelectCell(EventObject anEvent) {
		return editor.shouldSelectCell(anEvent);
	}
	public boolean stopCellEditing() {
		return editor.stopCellEditing();
	}
	public void cancelCellEditing() {
		editor.cancelCellEditing();
	}
	public void addCellEditorListener(CellEditorListener l) {
		editor.addCellEditorListener(l);
	}
	public void removeCellEditorListener(CellEditorListener l) {
		editor.removeCellEditorListener(l);
	}
	public Component getTreeCellEditorComponent(JTree t, Object v,
			boolean el, boolean expanded, boolean leaf, int row) {
		return editor.getTreeCellEditorComponent(t, v, el, expanded, leaf, row);
	}
	public Component getTableCellEditorComponent(JTable t, Object value,
			boolean sel, int row, int column) {
		return editor.getTableCellEditorComponent(t, value, sel, row, column);
	}
}